package com.alogic.es.core;

import com.alogic.lucene.analyzer.ik.IKAnalyzer;
import com.alogic.remote.Client;
import com.alogic.remote.ClientFactory;
import com.anysoft.util.*;
import org.apache.lucene.analysis.Analyzer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;

import java.util.Map;

/**
 * ES的indexer
 *
 * @since 1.6.13.9 [20200824 duanyy]
 */
public interface Indexer extends Configurable, XMLConfigurable, Reportable {
    /**
     * 获取id
     * @return id
     */
    public String getId();

    /**
     * 获取es数据库的地址(含索引)
     * @return 地址
     */
    public String getEndpoint();

    /**
     * 获取本库的Analyzer
     * @return Analyzer
     */
    public Analyzer getAnalyzer();

    /**
     * 获取客户端
     * @return 客户端
     */
    public Client getRemoteClient();

    /**
     * 输出属性信息到Properties
     * @param props Properties
     */
    public void writeProperties(Properties props);

    /**
     * 虚基类
     */
    public abstract static class Abstract implements Indexer {
        /**
         * a logger of log4j
         */
        protected static Logger LOG = LoggerFactory.getLogger(Indexer.class);

        /**
         * id
         */
        protected String id = "default";

        /**
         * 数据库地址
         */
        protected String endpoint = "http://${host}:${port}/${id}";

        /**
         * 访问数据库的keyId
         */
        protected String keyId;

        /**
         * 访问数据库的密钥
         */
        protected String secretKey;

        /**
         * analyzer
         */
        protected  Analyzer analyzer = null;

        @Override
        public String getId() {
            return id;
        }

        @Override
        public Analyzer getAnalyzer(){
            return analyzer;
        }

        @Override
        public String getEndpoint() {
            return endpoint;
        }

        @Override
        public void writeProperties(Properties props) {
            PropertiesConstants.setString(props,"$es.endpoint",this.getEndpoint());
            PropertiesConstants.setString(props,"$es.keyId",keyId);
            PropertiesConstants.setString(props,"$es.skey",secretKey);
        }

        @Override
        public void configure(Properties p) {
            id = PropertiesConstants.getString(p,"id",id,true);
            endpoint = PropertiesConstants.getString(p,"endpoint",endpoint,true);
            keyId = PropertiesConstants.getString(p,"keyId",keyId);
            secretKey = PropertiesConstants.getString(p,"skey",secretKey);

            if (analyzer == null){
                Factory<Analyzer> f = new Factory<Analyzer>();
                String analyzerClass = PropertiesConstants.getString(p,"analyzer", IKAnalyzer.class.getName());
                try {
                    analyzer = f.newInstance(analyzerClass, p);
                }catch (Exception ex){
                    LOG.error("can not create dic loader:" + analyzerClass);
                }
            }
        }

        @Override
        public void report(Element xml) {
            if (xml != null){
                XmlTools.setString(xml,"module",this.getClass().getName());
                XmlTools.setString(xml,"id",this.getId());
                XmlTools.setString(xml,"endpoint",this.getEndpoint());
            }
        }

        @Override
        public void report(Map<String, Object> json) {
            if (json != null){
                JsonTools.setString(json,"module",this.getClass().getName());
                JsonTools.setString(json,"id",this.getId());
                JsonTools.setString(json,"endpoint",this.getEndpoint());
            }
        }

        @Override
        public void configure(Element e, Properties p) {
            XmlElementProperties props = new XmlElementProperties(e,p);

            Element elem = XmlTools.getFirstElementByPath(e, "analyzer");
            if (elem != null){
                try {
                    Factory<Analyzer> f = new Factory<Analyzer>();
                    analyzer = f.newInstance(elem, p, "module", IKAnalyzer.class.getName());
                }catch (Exception ex){
                    LOG.info("can not create the analyzer: " + XmlTools.node2String(elem) );
                }
            }

            configure(props);
        }
    }

    /**
     * 缺省实现
     */
    public static class Default extends Abstract{
        private Client client = null;

        @Override
        public Client getRemoteClient() {
            return client;
        }

        @Override
        public void configure(Element e, Properties p) {
            XmlElementProperties props = new XmlElementProperties(e,p);

            Element elem = XmlTools.getFirstElementByPath(e, "analyzer");
            if (elem != null){
                try {
                    Factory<Analyzer> f = new Factory<Analyzer>();
                    analyzer = f.newInstance(elem, p, "module", IKAnalyzer.class.getName());
                }catch (Exception ex){
                    LOG.info("can not create the analyzer: " + XmlTools.node2String(elem) );
                }
            }

            elem = XmlTools.getFirstElementByPath(e,"client");
            if (elem != null) {
                client = ClientFactory.loadFrom(elem, "module", props);
            }

            configure(props);
        }

        @Override
        public void configure(Properties p){
            super.configure(p);

            if (client == null){
                client = com.alogic.remote.naming.ClientFactory.getCall(
                        PropertiesConstants.getString(p,"clientId","default")
                );
            }
        }
    }
}
